#ifndef PRIMITIVETRANSFORMER_H
#define PRIMITIVETRANSFORMER_H

#include <BLineArray>
#include <BViewer>
#include <BBillboard>
#include <BLine>
#include <BQuad>
#include <BCone>
#include <BSphere>
#include <BPicker>
#include <BRoundHandler>

#include "../LineStripe.h"
#include "../operas/TransOpera.h"
#include "../notes/TransformNote.h"
#include "../notes/RotationNote.h"
#include "../notes/ScalingNote.h"
#include "../TransformHandler.h"

class PrimitiveTransOpera : public Opera
{
public:
	PrimitiveTransOpera(BShape* shape, BVectorArray* vertices, const BIntSet& indexSet)
	{
		_shape = shape;
		_vertices = vertices;
		_indexSet = indexSet;
		for (int i = 0; i < _indexSet.size(); i++)
		{
			int index = _indexSet[i];
			const BVector& vec = vertices->at(index);
			_originPoints.append(vec);
			_newPoints.append(vec);
			_center += vec;
		}
		_center /= indexSet.size();
	}

	BShape* shape()
	{
		return _shape;
	}
	const BVectorArray& originPoints()
	{
		return _originPoints;
	}

	void freshNewPoints(const BMatrix& matrix)
	{
		for (int i = 0; i < _indexSet.size(); i++)
		{
			_newPoints[i] = _originPoints[i] * matrix;
		}
	}
	const BVectorArray& newPoints() const
	{
		return _newPoints;
	}
	BVectorArray& newPoints()
	{
		return _newPoints;
	}

	virtual bool redo()
	{
		if (!_shape)
			return false;
		for (int i = 0; i < _indexSet.size(); i++)
		{
			int index = _indexSet[i];
			_vertices->set(index, _newPoints[i]);
		}
		_shape->dirty();
		_shape->fresh();
		return true;
	}
	virtual bool undo()
	{
		if (!_shape)
			return false;
		for (int i = 0; i < _indexSet.size(); i++)
		{
			int index = _indexSet[i];
			_vertices->set(index, _originPoints[i]);
		}
		_shape->dirty();
		_shape->fresh();
		return true;
	}

private:
	BNode*				_parent;
	BShapeHolder		_shape;
	BVectorArray*		_vertices;
	BIntSet			_indexSet;
	BVector				_center;
	BVectorArray		_originPoints;
	BVectorArray		_newPoints;
};

class PrimitiveTransformer : public TransformHandler
{
public:
	PrimitiveTransformer();
	~PrimitiveTransformer();

	void setPrimitive(Primitive primitive);
	Primitive primitive() const;

	void setIndexSet(const BIntSet& indexSet);
	const BIntSet& indexSet() const;

protected:
	virtual void startTransform(const BMatrix& matrix) override;
	virtual void transforming(const BMatrix& matrix) override;
	virtual void finishTransform(const BMatrix& matrix) override;

protected:
	void slotAssetChanged(BObject* object, const BValue& value);
	void slotTragetDirty(BObject* object, const BValue& value);

protected:
	virtual void render(BRender& render);

	virtual void freshEvent(const BEvent& event);

protected:
	BHolder<Target>			_target;
	BHolder<BShape>			_shape;
	BHolder<BVectorArray>	_vertices;
	BIntSet				_indexSet;
	Primitive				_primitive;
	BBox					_pointsBox;

	bool					_dirty;
	bool					_spaceShown;
	bool					_leftPressed;
	BLine					_linePressed;
	BVector					_originCenter;
	BHolder<PrimitiveTransOpera>	_transOpera;
	int						_transStep;

};

#endif